package com.lwl.concurrency.disruptor;

import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.nio.ByteBuffer;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
 * <pre>
 *   BlockingWaitStrategy: 这是默认的策略,使用BlockingWaitStrategy和使用BlockingQueue是非常类似的,
 * 他们都使用锁和条件Condition进行数据的监控和线程的唤醒,因为涉及到线程的切换,BlockingWaitStrategy策略
 * 是最节省cpu,但是高并发情况下性能表现最差的等待策略.
 *   SleepingWaitStrategy: 这个策略也是对CPU的使用率非常保守的.它会在循环中不断等待数据.它会先进行自旋等待
 * 如果不成功,则使用Thread.yield()让出CPU,并最终使用LockSupport.parkNanos(1)进行线程休眠,以确保不占用太多的
 * CPU资源.因此这个策略会产生比较高的平均延时.典型的应用场景就是异步日志.
 *   YieldingWaitStrategy: 这个策略用于低延时的场合.消费者线程会不断循环监控缓冲区变化,
 *在循环内部使用Thread.yield()让出CPU给别的线程执行时间,如果需要一个高性能的系统,并且对延时比较有严格的要求,
 *可以考虑这种策略,最好有多余消费者线程数量的逻辑cpu数量,(逻辑cpu指双核四线程种的四线程
 *   BusySpinWaitStrategy: 采用死循环,消费者线程会尽最大努力监控缓冲区的变化.
 * 对延时非常苛刻的场景使用,物理cpu数量必须大于消费者线程数量
 * </pre>
 *
 * @author liwenlong - 2018/4/1 15:40
 */
public class Main {

    public static void main(String[] args) throws InterruptedException {
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        PCDataFactory factory = new PCDataFactory();
        //Disruptor要求必须将数组的大小设置的2的整数次方
        int bufferSize = 4;
        Disruptor<PCData> disruptor = new Disruptor<>(factory, bufferSize, threadFactory,
                ProducerType.MULTI, new BlockingWaitStrategy());

        Consumer consumer = new Consumer();

        disruptor.handleEventsWithWorkerPool(consumer, consumer, consumer, consumer);
        disruptor.start();

        RingBuffer<PCData> ringBuffer = disruptor.getRingBuffer();
        Producer producer = new Producer(ringBuffer);
        ByteBuffer buffer = ByteBuffer.allocate(8);

        long count = 0;
        while (true) {

            System.out.println(ringBuffer.remainingCapacity());
            System.out.println("add data " + (count++));
            buffer.putLong(0, count);
            producer.pushData(buffer);
            //Thread.sleep(1000);
            /*if (count == 10) {
                break;
            }*/
            System.out.println(ringBuffer.remainingCapacity());
        }


    }


}
